#ifndef Define_LcTimeSpaceMRF
#define Define_LcTimeSpaceMRF


#include <cstdio>
#include <cstdlib>
#include <iostream>

#include <cstring>
#include <opencv2/opencv.hpp>
#include <opencv2/flann/config.h>

#include <opencv2/legacy/legacy.hpp>		// EM
#include <opencv2/contrib/contrib.hpp>		// colormap
#include <opencv2/nonfree/nonfree.hpp>		// SIFT

#include <algorithm>

#include "LcBasic.h"

#include "VideoRead.h"

#include "FeatureComputer.h"

#include "Classifier.h"

#include "Bagging.h"

#include "ClassifierRank.h"

#include "LcGraphCut.h"

#include "MotionAnalysis.h"

#include "TimeSpaceMRF.h"

using namespace std;
using namespace cv;

typedef vector<Point2i> TimeEdge;

typedef std::pair< Point2i , TimeEdge > SuperpixelFlow;

typedef std::pair< vector<Point2f> , vector<Point2f> > PointMaps;

typedef std::pair< Point2i, PointMaps > Match;

class TimeSpaceMRF
{
public:
	float lambda;
	float nu;
	float heat_map_weight;
	float eta;

	bool IF_VISUAL;

	TimeSpaceMRF();

	void work(	vector< Mat > & frms,
				vector< Mat > & ress,				  
				LocalSensitiveBagging & crank_bagging,
				LcHistogram & global_extractor);

	void getAllInfo(	vector< Mat > & frms,
						LocalSensitiveBagging & crank_bagging,
						LcHistogram & global_extractor,
						vector< int > & n_nodes,
						vector< int > & node_shift,
						vector< Mat >  & node_descs,						
						vector< Mat >  & label_maps,
						vector< SuperpixelFlow> & superpixel_flows,
						vector< Mat >  & adj_mats);

	LcValidator predict(	vector< int > & n_nodes,
							vector< int > & node_shift,
							vector< Mat >  & node_descs,						
							vector< Mat >  & label_maps,
							vector< SuperpixelFlow> & superpixel_flows,
							vector< Mat >  & adj_mats, 
							Mat & gt,
							vector< Mat > & ress);

	int n_frame;
	int t_win;

private:

	void saveSrc( vector< Mat > & frms );

	void getLikeli( vector< Mat > & frms,
					vector< Mat > & likeli,
					LocalSensitiveBagging & crank_bagging,
					LcHistogram & global_extractor);

	void saveLikeli( vector< Mat > & likeli );

	void getSLIC(	vector< Mat > & frms,
					vector< Mat > & likeli,
					vector< Mat >  & label_maps,
					vector< Mat >  & node_descs,
					vector< Mat >  & adj_mats,
					vector< int > & n_nodes,
					vector< int > & node_shift,
					vector< vector<Point2f> > & node_centers);

	void getSuperpixelFlow(	vector< SuperpixelFlow> & superpixel_flows,
							vector< Mat > & frms,
							vector< Mat >  & label_maps,
							vector< Mat >  & node_descs,
							vector< vector<Point2f> > & node_centers);

	Match getMatch(	int id1 , int id2 ,
					vector<Mat > & frms,
					vector< vector< Point2f > > & key_points,
					LcKLT & my_tracker);

	void getMatches(vector< Mat > & frms, vector<Match> & matches);

	void getGoodPoints(	vector< Mat > & frms,
						vector< vector< Point2f > > & key_points,
						LcKLT & my_tracker);

	void getMeanOpt( vector< Point2f > & mean_opt1,
		Mat & label_map1, vector< Point2f > & po1,
		vector< Point2f > & po2, int n1,float frame_diff);

	void getFlowMap(	vector< Point2i> & _maps,
						vector< Point2f > & mean_opt1,
						Mat & label_map1, Mat & label_map2,
						int n1, int n2);

	void saveOptFlow(	int frame_id1, int frame_id2,
						vector< Point2f > & node_center,
						vector< Point2f > & mean_opt1);

	void saveSuperpixelFlow(	vector<int> & n_nodes,
								vector< int > & node_shift,
								vector< vector<Point2f> > & node_centers,
								vector< SuperpixelFlow> & superpixel_flows);

	void getNodeWeight(		vector< Mat >  & node_descs,
							vector< Mat > & node_weights);

	void buildAndCut(	vector< Mat > & ress,
						vector< int > & n_nodes,
						vector< int > & node_shift,
						vector< Mat >  & node_descs,						
						vector< Mat >  & label_maps,
						vector< SuperpixelFlow> & superpixel_flows,
						vector< Mat >  & adj_mats);


	void saveRess( vector< Mat > & ress );

};

#endif